Skip to content

Minjeong / 12월 2주차 / 4문제#105

Merged
Mingguriguri merged 4 commits intomainfrom
minjeong
Dec 15, 2024
Merged

Minjeong / 12월 2주차 / 4문제#105
Mingguriguri merged 4 commits intomainfrom
minjeong

Conversation

@Mingguriguri
Copy link
Collaborator

@Mingguriguri Mingguriguri commented Dec 14, 2024

🌱WIL

이번 한 주의 소감을 작성해주세요!

  • 이번 주에는 너무 바빠서 코테 문제 푸는 게 너무 빡셌다.. 시간 내는 게 중요한 것 같다. 또 TIL이나 내용 정리를 많이 못했는데 다음 주에는 제대로 할 수 있도록 시간을 꼭 내야겠다.
  • 계속 DP만 풀다가 오랜만에 구현, DFS 문제를 푸니까 헷갈리고 어려웠다.. 여러 문제를 골고루 푸는 것도 중요한 것 같다.

🚀주간 목표 문제 수: 4개

푼 문제


백준 #11660. 구간 합 구하기 5 : DP / 실버1

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  1. 입력 처리:
    • 숫자 표 크기 N, 쿼리 수 M 입력받는다.
    • 숫자 표를 입력받아 grid 배열 생성한다.
  2. 누적합 테이블 계산:
    • prefix_sum[i][j]를 점화식을 통해 계산한다.
  3. 범위 합 계산:
    • 각 쿼리에 대해 주어진 범위를 누적합 공식으로 계산한다.

🚩제출한 코드

import sys
input = sys.stdin.readline

# 누적합 테이블 계산 함수
def get_prefix_sum(grid, N):
    prefix_sum = [[0] * (N+1) for _ in range(N+1)]
    for i in range(1, N+1):
        for j in range(1, N+1):
            prefix_sum[i][j] = (
                grid[i-1][j-1]
                + prefix_sum[i-1][j]
                + prefix_sum[i][j-1]
                - prefix_sum[i-1][j-1]
            )
    return prefix_sum

# 입력
N, M = map(int, input().split())
grid = [list(map(int, input().split())) for _ in range(N)]

# 누적합
prefix_sum = get_prefix_sum(grid, N)

# 범위 합 계산
for _ in range(M):
    x1, y1, x2, y2 = map(int, input().split())
    answer = (
        prefix_sum[x2][y2]
        - prefix_sum[x1-1][y2]
        - prefix_sum[x2][y1-1]
        + prefix_sum[x1-1][y1-1]
    )
    print(answer)

💡TIL

배운 점이 있다면 입력해주세요

  • 기존 누적합 방식을 2차원에서 구간합을 구하는 방법을 배울 수 있는 문제였다.
  • 점화식 공식이 이해가 되지 않았지만, 겹치는 부분을 빼줘야 하는 원리를 하나씩 뜯어고치면서 이해하였다.
  • 복습이 필수!!

백준 #10844. 쉬운 계단 수: DP / 실버1

🚩제출한 코드

n = int(input())

num = [[0]*10 for _ in range(n+1)]
num[0] = [1,1,1,1,1,1,1,1,0] #0행에 들어가는 값들을 계단수의 경우의수로 초기화

for i in range(1,n+1):
    for j in range(10): #0일때, 9일때, 나머지인 경우를 점화식을 토대로 코드 작성
        if j == 0: 
            num[i][j] = num[i-1][1]
        elif j == 9:
            num[i][j] = num[i-1][8]
        else:
            num[i][j] = num[i-1][j-1] + num[i-1][j]

answer = sum(num[n]) % 100000000
print(answer)

💡TIL

배운 점이 있다면 입력해주세요

  • DP의 점화식을 잘 세우는 것이 중요한 문제였다.

백준 #1914. 하노이탑: DP / 실버1

🚩제출한 코드

#하노이 함수
def hanoi_f(one, three, n):
    if n == 1:
        print(one,three)
        return
    
    hanoi_f(one, 6-one-three, n-1) #1단계 (1->2)
    print(one, three) #2단계 (마지막원반 1->3)
    hanoi_f(6-one-three, three, n-1) #3단계 (2->3)

#메인
n = int(input())
print(2**n-1)
if n <= 20:
    hanoi_f(1,3,n)

💡TIL

배운 점이 있다면 입력해주세요

  • 문제를 풀 때, 바로 접근하지 말고, n=1, n=2, n=3, … 차례차례 나열해보며 규칙성을 파악해보자
  • 힌트를 듣고 마구잡이로 집어넣지 말고, 내 코드와 맥락이 맞는지 파악해보자
  • 공식의 경우, 미리 알고 있으면 좋겠지만, 직접 나열해보고 규칙을 찾아가는 식으로 해도 풀 수 있다.
  • 멘탈을 부여잡자

백준 #14500. 테트로미노: 구현 / 골드4

🚩플로우 (선택)

코드를 풀이할 때 적었던 플로우가 있나요?

  1. 입력값 초기화
  • 종이 크기 N x M을 입력받는다.
  • 종이에 쓰인 숫자들을 이차원 배열 graph에 저장한다.
  • 방문 여부를 체크하는 visited 배열을 초기화한다.
  1. 탐색 방향 설정
  • 테트로미노의 모양을 만들기 위해 상하좌우 이동을 위한 방향 벡터 dx, dy를 설정한다.
  1. DFS 탐색: ㅗ 모양 제외
  • 모든 좌표에서 DFS를 시작한다.
  • DFS는 현재 위치에서 상하좌우로 이동하며 4칸을 방문한다.
  • 방문한 칸들의 합을 계산해 최댓값을 갱신한다.
  • 이미 방문한 칸은 다시 방문하지 않도록 체크하며, DFS가 끝난 후 복구한다.
  1. ㅗ 모양 탐색 (별도 처리)
  • DFS로 탐색할 수 없는 ㅗ 모양은 별도로 처리한다.
  • 모든 좌표를 중심으로 상하좌우 중 3개 방향을 선택해 합을 계산한다.
  • 범위를 벗어나거나 잘못된 위치일 경우 계산하지 않는다.
  1. 결과 출력
  • 모든 좌표에서 탐색이 끝난 후, 최댓값을 출력한다.

🚩제출한 코드

n, m = map(int, input().split())
graph = [list(map(int, input().split())) for _ in range(n)]
visited = [[False] * m for _ in range(n)]

# 방향 설정 (상, 하, 좌, 우)
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

# 최댓값 저장 변수
max_value = 0


# DFS 탐색 (ㅗ 모양 제외)
def dfs(x, y, count, total):
    global max_value
    # 테트로미노 4칸 채웠을 경우
    if count == 4:
        max_value = max(max_value, total)
        return

    # 상하좌우 탐색
    for i in range(4):
        nx, ny = x + dx[i], y + dy[i]
        # 범위 내에 있고, 방문하지 않은 경우
        if 0 <= nx < n and 0 <= ny < m and not visited[nx][ny]:
            visited[nx][ny] = True
            dfs(nx, ny, count + 1, total + graph[nx][ny])
            visited[nx][ny] = False  # 백트래킹


# ㅗ 모양 탐색
def check_t_shape(x, y):
    global max_value
    # 중심 기준 4방향 중 3개를 선택 (ㅗ, ㅜ, ㅏ, ㅓ)
    for i in range(4):
        total = graph[x][y]
        for j in range(3):  # 현재 제외한 3방향 탐색
            k = (i + j) % 4
            nx, ny = x + dx[k], y + dy[k]
            if 0 <= nx < n and 0 <= ny < m:
                total += graph[nx][ny]
            else:  # 범위를 벗어나면 ㅗ 모양이 성립하지 않음
                break
        else:  # 모든 3방향 탐색이 유효한 경우
            max_value = max(max_value, total)


# 모든 좌표에서 테트로미노 탐색
for i in range(n):
    for j in range(m):
        visited[i][j] = True
        dfs(i, j, 1, graph[i][j])  # DFS 시작
        visited[i][j] = False
        check_t_shape(i, j)  # ㅗ 모양 탐색

# 결과 출력
print(max_value)

💡TIL

배운 점이 있다면 입력해주세요

  • 이 문제는 DFS 백트래킹과 시뮬레이션을 조합해야 했다.
  • 초기에는 DFS만으로 모든 테트로미노 모양을 탐색하려 했지만, ㅗ 모양이 제외된다는 점을 알게 되었다.
  • 탐색 범위 예외 처리가 중요했다. 종이 밖으로 벗어나는 경우를 조건문으로 철저히 검사해야 했다.
  • 백트래킹과 방문 처리를 통해 효율적으로 테트로미노를 배치할 수 있었다.
    이 문제를 통해 DFS 탐색과 예외 처리의 중요성을 다시 한번 깨달았다.

@YoonYn9915
Copy link
Member

저는 테트로미노 문제를 DFS로 풀다 실패해서 브루트포스로 풀었는데 민정님은 DFS로 구현 완료하셨네요 👍
PR후 DFS방식으로 푼 블로그를 탐색해보니 보통 일반 브루트포스보다 DFS+브루트포스가 훨씬 더 느리더라구요. 그래서 추가로 다른 블로그를 찾아봤는데 가지치기를 진행한 경우도 있어서 공유드립니다. 이 문제는 코드에 비해 시간 제한이 넉넉해서 굳이 가지치기를 하지 않아도 되지만 참고하면 좋을것 같습니다.

보통 DFS 구현시 종료조건2와 같은 depth체크만하는데 종료조건1을 넣어서 블록 4개를 모두 다 더하지 않은 상황에서도 최댓값이 되지 않을 걸 미리 알고 쳐내는 방식이 흥미로웠습니다.

def dfs(x, y, step, total):
    # 종료조건1) 탐색을 계속 진행하여도 최댓값에 못 미치는 경우
    if total + max_val*(4-step) <= answer:
        return

    # 종료조건2) 블록 4개를 모두 활용한 경우
    if step == 4:
        answer = max(answer, total)
        return

출처: https://heytech.tistory.com/364

@Mingguriguri
Copy link
Collaborator Author

@YoonYn9915 어쩐지 제출할 때 엄청 느리게 채점되더라구요.. 이 문제는 DFS 보다는 완전탐색 문제였던 것 같아요! 추가적인 블로그도 공유해주시고, 구체적인 피드백 감사합니다!!

@Mingguriguri Mingguriguri merged commit a1ca274 into main Dec 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments